package com.deep.test.aio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.StandardSocketOptions;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousChannelGroup;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;

/**
 * <p>Description:</p>
 * Created with IDEA
 * author:hudepin
 * createTime:2018/5/23 11:09
 */
public class AioServer {
    private AsynchronousServerSocketChannel server;

    public static void main(String[] args) {
        AioServer aServer = new AioServer();
        aServer.init("127.0.0.1",1256);
    }

    private void init(String host,int port) {
        try {
            AsynchronousChannelGroup aChannelGroup = AsynchronousChannelGroup.withCachedThreadPool(Executors.newCachedThreadPool(),32);
            server = AsynchronousServerSocketChannel.open(aChannelGroup);
            server.setOption(StandardSocketOptions.SO_REUSEADDR,true);
            //The size of the socket receive buffer.
            server.setOption(StandardSocketOptions.SO_RCVBUF,16*1024);
            //端口绑定
            server.bind(new InetSocketAddress(host,port));
            System.out.println("start listen host:"+host+",port:"+port);
            System.out.println("channel provider:"+server.provider());
            server.accept(null, new CompletionHandler<AsynchronousSocketChannel, Object>() {
                final ByteBuffer buffer = ByteBuffer.allocate(1024);
                @Override
                public void completed(AsynchronousSocketChannel result, Object attachment) {
                    System.out.println("waiting....");
                    buffer.clear();
                    try {
                        //把socket中的数据读取到buffer中
                        result.read(buffer).get();
                        buffer.flip();
                        System.out.println("Echo " + new String(buffer.array()).trim() + " to " + result);
                        //把收到的直接返回给客户端
                        result.write(buffer);
                        buffer.flip();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (ExecutionException e) {
                        e.printStackTrace();
                    } finally {
                        try {
                            //关闭处理完的socket，并重新调用accept等待新的连接
                            result.close();
                            server.accept(null, this);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }

                @Override
                public void failed(Throwable exc, Object attachment) {
                    System.out.println("failed:"+exc.getCause());
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
        //因为AIO不会阻塞调用进程，因此必须在主进程阻塞，才能保持进程存活。
        try {
            Thread.sleep(Integer.MAX_VALUE);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
